// Variable.cpp: implementation of the Variable class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Variable.h"
#include "Math.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

UE_IMPLEMENT_DYNAMIC(Variable, SmallObject);

Variable::Variable()
{
	m_nType = ID;
	m_nDataType = STRING;
	m_nState = UNKNOWN;
}

Variable::Variable(const Variable& Value)
{
	m_nType = ID;
	m_nDataType = STRING;
	m_nState = UNKNOWN;
	*this = Value;
}

Variable::~Variable()
{
	
}

Variable& Variable::operator=(const Variable& Value)
{
	if(m_nDataType == PART)
	{
		ASSERT(FALSE);
		return *this;
	}
	if(this == &Value)
		return *this;
	
	m_strSymbol = Value.m_strSymbol;
	m_nDataType = Value.m_nDataType;
	m_nType = Value.m_nType;
	try
	{
		m_Value = Value.m_Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable& Variable::operator=(const _variant_t& Value)
{
	try
	{
		m_Value = Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}

	m_nState = MODIFY;	
	return *this;
}

Variable& Variable::operator=(const INT& Value)
{
	try
	{
		m_Value = (LONG)Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable& Variable::operator=(const DOUBLE& Value)
{
	if(m_nDataType == PART)
	{
		ASSERT(FALSE);
		return *this;
	}
	try
	{
		m_Value = Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable& Variable::operator=(const LONG& Value)
{
	if(m_nDataType == PART)
	{
		ASSERT(FALSE);
		return *this;
	}
	try
	{
		m_Value = Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable& Variable::operator=(const SHORT& Value)
{
	if(m_nDataType == PART)
	{
		ASSERT(FALSE);
		return *this;
	}
	try
	{
		m_Value = Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable& Variable::operator=(const FLOAT& Value)
{
	if(m_nDataType == PART)
	{
		ASSERT(FALSE);
		return *this;
	}
	try
	{
		m_Value = Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable& Variable::operator=(const CString& Value)
{
	try
	{
		m_Value = Value;
	}
	catch(_com_error e)
	{
		ErrorAlert(e);
	}
	
	m_nState = MODIFY;
	return *this;
}

Variable::operator DOUBLE()
{
	ASSERT(IsKnown());
	return vtod(m_Value);
}

Variable::operator FLOAT()
{
	ASSERT(IsKnown());
	ASSERT(m_nDataType != PART);
	return vtof(m_Value);
}

Variable::operator _variant_t()
{
	ASSERT(IsKnown());
	ASSERT(m_nDataType != PART);
	return m_Value;
}

Variable::operator LONG()
{
	ASSERT(IsKnown());
	return vtoi(m_Value);
}

Variable::operator INT()
{
	ASSERT(IsKnown());
	ASSERT(m_nDataType != PART);
	return vtoi(m_Value);
}

Variable::operator SHORT()
{
	ASSERT(IsKnown());
	ASSERT(m_nDataType != PART);
	return vtoi(m_Value);
}

Variable::operator CString()
{
	ASSERT(IsKnown());
	return vtos(m_Value);
}

Variable::operator Part*()
{
	ASSERT(IsKnown());
	if(m_nDataType != PART)
	{
		ASSERT(FALSE);
		return NULL;
	}
	return NULL;
}

Variable::operator PropertyStackInterface*()
{
	ASSERT(IsKnown());
	return NULL;
}

Variable Variable::operator-()
{
	ASSERT(IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);

	Variable variable(*this);;
	if(m_nDataType == INTEGER)
	{
		variable = -vtoi(m_Value);
	}
	else if(m_nDataType == DOUBLEX)
	{
		variable = -vtod(m_Value);
	}
	
	return variable;
}

Variable Variable::operator+(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != PART);
	Variable variable(*this);;
	if(m_nDataType == INTEGER)
	{
		variable = vtoi(m_Value) + vtoi(Value.m_Value);
	}
	if(m_nDataType == DOUBLEX)
	{
		variable = vtod(m_Value) + vtod(Value.m_Value);
	}
	else if(m_nDataType == STRING)
	{
		variable = vtos(m_Value) + vtos(Value.m_Value);
	}
	return variable;
}

Variable Variable::operator-(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	Variable variable(*this);
	if(m_nDataType == INTEGER)
	{
		variable = vtoi(m_Value) - vtoi(Value.m_Value);
	}
	if(m_nDataType == DOUBLEX)
	{
		variable = vtod(m_Value) - vtod(Value.m_Value);
	}
	return variable;
}

Variable Variable::operator*(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	Variable variable(*this);
	if(m_nDataType == INTEGER)
	{
		variable = vtoi(m_Value) * vtoi(Value.m_Value);
	}
	else if(m_nDataType == DOUBLEX)
	{
		variable = vtod(m_Value) * vtod(Value.m_Value);
	}
	return variable;
}

Variable Variable::operator/(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	Variable variable(*this);
	if(m_nDataType == INTEGER)
	{
		variable = vtoi(m_Value) / vtoi(Value.m_Value);
	}
	if(m_nDataType == DOUBLEX)
	{
		variable = vtod(m_Value) / vtod(Value.m_Value);
	}
	return variable;
}

Variable Variable::operator>=(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	
	Variable variable;
	variable.DataType(INTEGER);
	variable = (vtod(m_Value) >= vtod(Value.m_Value));
	return variable;
}

Variable Variable::operator==(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != PART);

	Variable variable;
	variable.DataType(INTEGER);
	if(m_nDataType == STRING)
	{
		variable = (vtos(m_Value) == vtos(Value.m_Value));
	}
	else if(m_nDataType == INTEGER)
	{
		variable = (vtoi(m_Value) == vtoi(Value.m_Value));
	}
	else
	{
//		DOUBLE db = fabs(atof(vtos(m_Value)) - atof(vtos(Value.m_Value)));
		variable = (fabs(atof(vtos(m_Value)) - atof(vtos(Value.m_Value))) > 0.001)?0:1;
	}
	return variable;
}

Variable Variable::operator<=(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	
	Variable variable;
	variable.DataType(INTEGER);
	variable = (vtod(m_Value) <= vtod(Value.m_Value));
	return variable;
}

Variable Variable::operator>(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	
	Variable variable;
	variable.DataType(INTEGER);
	variable = (vtod(m_Value) > vtod(Value.m_Value));
	return variable;
}

Variable Variable::operator<(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	
	Variable variable;
	variable.DataType(INTEGER);
	variable = (vtoi(m_Value) < vtoi(Value.m_Value));
	return variable;
}

Variable Variable::operator!=(Variable&Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != PART);

	Variable variable;
	variable.DataType(INTEGER);
	if(m_nDataType == STRING)
	{
		variable = (vtos(m_Value) != vtos(Value.m_Value));
	}
	else if(m_nDataType == INTEGER)
	{
		variable = (vtoi(m_Value) != vtoi(Value.m_Value));
	}
	else
	{
//		DOUBLE db = fabs(atof(vtos(m_Value)) - atof(vtos(Value.m_Value)));
		variable = (fabs(atof(vtos(m_Value)) - atof(vtos(Value.m_Value))) > 0.1)?1:0;
	}
	return variable;
}

Variable Variable::operator&&(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	
	Variable variable;
	variable.DataType(INTEGER);
	variable = (vtoi(m_Value) && vtoi(Value.m_Value));
	return variable;
}

Variable Variable::operator||(Variable& Value)
{
	ASSERT(IsKnown());
	ASSERT(Value.IsKnown());
	ASSERT(m_nDataType != STRING);
	ASSERT(m_nDataType != PART);
	
	Variable variable;
	variable.DataType(INTEGER);
	variable = (vtoi(m_Value) || vtoi(Value.m_Value));
	return variable;
}